package optimizer;

import java.util.List;

import llvmir.value.Value;
import llvmir.value.instructions.Br;
import llvmir.value.structure.BasicBlock;
import llvmir.value.structure.Function;
import llvmir.value.structure.Module;

public class OtherOptimizer {
    public static boolean OPEN = false;

    public static void optimize() {
        optimizeJump();
    }

    public static void optimizeJump() {
        // 如果一个基本块只有一条无条件跳转指令
        // 那么将所有跳转到该基本块的指令改为跳转到该基本块的目标
        Module module = Module.getInstance();
        List<Value> functionList = module.getFunctions();
        Value mainFunction = module.getMainFunction();
        for (Value function : functionList) {
            Function f = (Function) function;
            for (BasicBlock bb : f.getBasicBlocks()) {
                if (bb.getInstructions().size() == 1 && bb.getInstructions().get(0) instanceof Br) {
                    Br br = (Br) bb.getInstructions().get(0);
                    if (br.getOperands().size() == 1) {
                        BasicBlock target = (BasicBlock) br.getOperands().get(0);
                        for (BasicBlock bb2 : f.getBasicBlocks()) {
                            for (Value inst : bb2.getInstructions()) {
                                if (inst instanceof Br) {
                                    Br br2 = (Br) inst;
                                    if (br2.getOperands().size() == 1 && br2.getOperands().get(0) == bb) {
                                        br2.getOperands().set(0, target);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        // 对main函数进行相同的操作
        for (BasicBlock bb : ((Function) mainFunction).getBasicBlocks()) {
            if (bb.getInstructions().size() == 1 && bb.getInstructions().get(0) instanceof Br) {
                Br br = (Br) bb.getInstructions().get(0);
                if (br.getOperands().size() == 1) {
                    BasicBlock target = (BasicBlock) br.getOperands().get(0);
                    for (BasicBlock bb2 : ((Function) mainFunction).getBasicBlocks()) {
                        for (Value inst : bb2.getInstructions()) {
                            if (inst instanceof Br) {
                                Br br2 = (Br) inst;
                                if (br2.getOperands().size() == 1 && br2.getOperands().get(0) == bb) {
                                    br2.getOperands().set(0, target);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
